home *** CD-ROM | disk | FTP | other *** search
- /*
- * wimp.c --- Intuition interface
- *
- * Author: ppessi <Pekka.Pessi@hut.fi>
- *
- * Copyright (c) 1993 Pekka Pessi
- *
- * Created : Wed Nov 10 11:15:14 1993 ppessi
- * Last modified: Fri Feb 4 03:24:24 1994 ppessi
- *
- * $Log: wimp.c,v $
- * Revision 3.4 1994/05/14 14:12:58 ppessi
- * Merged changes from Napsaterm 3.5 by R. Knop
- *
- * Revision 3.3 1994/02/25 02:02:17 ppessi
- * Updated some IDCMP macros
- *
- * Revision 3.2 1994/01/08 08:58:31 ppessi
- * Added optional error message requesters;
- * fixed menu_move() and menu_execute()
- *
- * Revision 3.1 94/01/07 22:51:48 ppessi
- * Version 3 beta
- *
- * Revision 2.3 93/11/24 18:31:01 ppessi
- * Changed the memory management slightly
- *
- * Revision 2.2 93/11/18 18:33:24 ppessi
- * Changed menu format.
- *
- * Revision 2.1 93/11/17 15:41:30 ppessi
- * Moved the rest of the Intuition code here
- * mapwindow() opens the window with OpenWindowTags()
- *
- * Revision 2.0 93/11/15 03:39:31 ppessi
- * Version 2 initial revision
- *
- */
-
- RCS_ID_C= "$Id: wimp.c,v 3.4 1994/05/14 14:12:58 ppessi Exp $";
-
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "nifty.h"
- #include "amiga.h"
- #include "napsaprefs.h"
-
- #include "nio.h"
- #include "display.h"
- #include "dispmacros.h"
-
- #include "wimp.h"
-
- #include <assert.h>
- #include <stdarg.h>
-
- #include <intuition/intuition.h>
-
- #if USE_PRAGMAS
- #include <proto/intuition.h>
- #endif
- #if USE_INLINE
- #include <inline/intuition.h>
- #endif
- #if USE_CLIB
- #include <clib/intuition_protos.h>
- #endif
-
- /* This is private */
- #ifndef TEKTRONICS /*added RKNOP 940328*/
- static struct Window *w = NULL;
- #else
- struct Window *w = NULL; /*tek4010.c needs this window definition*/
- #endif
- static struct MsgPort *winport = NULL;
- /* We publish only the geometry */
- struct geometry wm = { -1, -1, 80, 24 };
-
- #define WM_MINWIDTH 180 /* Minimum height */
-
- static struct {
- UWORD left, top, width, height;
- } zoom_size =
- { 0, 0, WM_MINWIDTH, 0 };
-
- #define MY_IDCMP_FLAGS \
- ( IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE | IDCMP_MENUPICK | \
- IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY | \
- IDCMP_CHANGEWINDOW )
-
- static void parsegeometry(char *gs, struct geometry *gm);
- int mapwindow(void);
- void unmapwindow(void);
-
- void domouse(struct IntuiMessage * msg);
-
- /*
- * display start routine -- sets up display
- */
- void dsinit(void)
- {
- initkeys();
- initnations();
- initfonts();
-
- /* Set the default geometry */
- clearSelection();
-
- disp.visual = np.visual;
- disp.blink = np.blink;
- disp.invert = np.invert;
- disp.style = 0;
- disp.curx = disp.cury = disp.winheight = disp.winwidth = 0;
-
- allocate_display(MAXWIDTH, MAXHEIGHT);
-
- parsegeometry(np.geometry, &wm);
-
- if (!mapwindow())
- fatalError(MEMORY_ERROR_MSG);
-
- dssizewindow(0, 0, np.col80);
-
- reset_display(0);
- redraw_display(1);
- }
-
- long dsmask(void)
- {
- if (w)
- return 1 << winport->mp_SigBit;
- else
- return 0;
- }
-
- /*
- * Quit
- */
- void dsquit(void)
- {
- ClipClose();
- free_display();
-
- if (w)
- unmapwindow();
-
- deinitfonts();
- deinitkeys();
- deinitnations();
- }
-
- /*
- * Set the geometry as specified
- */
- static void parsegeometry(char *gs, struct geometry *gm)
- {
- long left, top, width, height;
- int eaten;
-
- if (gs == NULL || gs[0] == '\0')
- return;
-
- eaten = StrToLong(gs, &left);
- gs += eaten;
- if (eaten < 0 || *gs++ != '/')
- return;
-
- eaten = StrToLong(gs, &top);
- gs += eaten;
- if (eaten < 0 || *gs++ != '/')
- return;
-
- eaten = StrToLong(gs, &width);
- gs += eaten;
- if (eaten < 0 || *gs++ != '/')
- return;
- if (np.col80)
- width = 80;
-
- eaten = StrToLong(gs, &height);
- if (eaten < 0 )
- return;
-
- /* set user's geometry */
- gm->left = left;
- gm->top = top;
- gm->width = width;
- gm->height = height;
- }
-
- /*
- * Wait a key press
- */
- void waitToEnd(void)
- {
- int class;
- struct IntuiMessage *msg;
-
- dscursoroff();
- dscursormove(NEXT_LINE, 1);
- (void) dsstyle(INVERSE1);
- dsputs("** Press any key to exit. **");
- dscursoron();
-
- do {
- msg = (struct IntuiMessage *)GetMsg(winport);
- if (!msg) {
- WaitPort(winport);
- continue;
- }
- class = msg->Class;
- ReplyMsg(msg);
- } while (class != RAWKEY);
- }
-
- /*
- * DisplayBeep()
- */
- void displaybell(void)
- {
- if (w)
- DisplayBeep(w->WScreen);
- }
-
- /*
- * Event handler for intuition events.
- */
- void dspoll(void)
- {
- struct IntuiMessage *msg;
-
- while (w && (msg = (struct IntuiMessage *)GetMsg(winport))) {
- switch(msg->Class) {
- case IDCMP_RAWKEY:
- dokeys(msg);
- break;
- case IDCMP_CLOSEWINDOW:
- ReplyMsg((struct Message *)msg);
- dsquit();
- amigaquit();
- exit(0);
- break;
- case IDCMP_NEWSIZE:
- ReplyMsg((struct Message *)msg);
- redraw_display(1);
- break;
- case IDCMP_MENUPICK:
- domenu(msg);
- break;
- case IDCMP_MOUSEMOVE:
- case IDCMP_MOUSEBUTTONS:
- domouse(msg);
- break;
- #ifdef OWNICONIFY
- case IDCMP_GADGETDOWN:
- if (DoubleClick(secs, mics, msg->Seconds, msg->Micros)) {
- ReplyMsg((struct Message *)msg);
- while (msg = (struct IntuiMessage *)GetMsg(w->UserPort))
- ReplyMsg((struct Message *)msg);
- deiconify();
- mapwindow();
- }
- else {
- secs = msg->Seconds; mics = msg->Micros;
- ReplyMsg((struct Message *)msg);
- }
- break;
- #endif
- default:
- ReplyMsg((struct Message *)msg);
- }
- }
- }
-
- /*
- * Convert Amiga mouse events to doselection() format
- */
- void domouse(struct IntuiMessage *msg)
- {
- int x, y, count = 0;
-
- x = GETXPOS(msg->MouseX);
- y = GETYPOS(msg->MouseY);
- BOUNDSCK(x, 0, disp.winwidth);
- BOUNDSCK(y, 0, disp.winheight-1);
-
- if (msg->Class == MOUSEBUTTONS) {
- if (np.mouse & MOUSE_BOTH) {
- register char mousequal = 0x40;
-
- iobuf[0] = ESC;
- iobuf[1] = 'M';
-
- if (msg->Code == SELECTUP) {
- mousequal |= 1 << 5;
- count = 5;
- }
- if (msg->Code == SELECTDOWN) {
- mousequal |= 1 << 4;
- count = 5;
- }
- if (msg->Qualifier & IEQUALIFIER_CAPSLOCK)
- mousequal |= 1 << 3;
- if (msg->Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
- mousequal |= 1 << 2;
- if (msg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
- mousequal |= 1 << 1;
- if (msg->Qualifier & IEQUALIFIER_CONTROL)
- mousequal |= 1 << 0;
- iobuf[2] = mousequal;
- iobuf[3] = ' ' + x;
- iobuf[4] = ' ' + y;
- }
-
- if (msg->Code == SELECTDOWN) {
- ReportMouse(TRUE, w);
- doselection(LBDOWN, x, y);
- }
- if (msg->Code == SELECTUP) {
- ReportMouse(FALSE, w);
- doselection(LBUP, x, y);
- }
- } else if (msg->Class == MOUSEMOVE) {
- doselection(LMOVE, x, y);
- }
-
- ReplyMsg((struct Message *)msg);
- if (count)
- nwrite(iobuf, count);
- }
-
- #include <utility/tagitem.h>
-
- int mapwindow(void)
- {
- char *pubscname = np.pubscname;
-
- /* Try to find specified public screen */
- struct Screen *s = LockPubScreen(pubscname);
- /* If not successful, try default */
- if (!s && pubscname) {
- s = LockPubScreen(pubscname = NULL);
- }
- /* Give up */
- if (!s)
- return 0;
-
- #define OPTIONAL(condition, tag) ((condition) ? (tagname), TAG_IGNORE)
-
- zoom_size.top = wm.top < 0 ? s->BarHeight : wm.top;
- if (wm.left != -1) {
- zoom_size.left = wm.left;
- }
- zoom_size.height = s->WBorTop + s->Font->ta_YSize + 1;
-
- w = OpenWindowTags(NULL,
- WA_PubScreen, s,
- WA_InnerWidth, (ULONG)wm.font.w * wm.width,
- WA_InnerHeight, (ULONG)wm.font.h * wm.height,
- wm.left != -1 ? WA_Left : TAG_IGNORE, (ULONG)wm.left,
- WA_Top, zoom_size.top,
- np.size_gadget ? WA_SizeGadget : TAG_SKIP, 1L,
- np.size_gadget == SIZE_COLUMN ?
- WA_SizeBRight : WA_SizeBBottom, 1L,
- WA_ScreenTitle, ProgName,
- WA_Zoom, &zoom_size,
- WA_Flags,
- WFLG_SMART_REFRESH | WFLG_CLOSEGADGET
- | WFLG_DEPTHGADGET | WFLG_DRAGBAR
- | WFLG_NOCAREREFRESH | WFLG_ACTIVATE,
- WA_IDCMP, MY_IDCMP_FLAGS,
- TAG_DONE );
- UnlockPubScreen(NULL, s);
-
- if (!w)
- return 0;
-
- winport = w->UserPort;
- initmenus();
-
- #if 0
- Move(rp, 0, 0);
- BltBitMapRastPort(rp->BitMap, 0, 0, rp, w->BorderLeft, w->BorderTop,
- w->Width - w->BorderLeft - w->BorderRight,
- w->Height - w->BorderTop - w->BorderBottom, WHITE);
- #endif
-
- return 1;
- }
-
- void unmapwindow(void)
- {
- if (w) {
- wm.left = w->LeftEdge;
- wm.top = w->TopEdge;
-
- ClearMenuStrip(w);
-
- deinitmenus();
-
- ModifyIDCMP(w, 0);
- CloseWindow(w);
- w = NULL;
-
- deinitdrawing();
- }
- }
-
- /*
- * Handle resizing the display
- */
- int resize_display(void)
- {
- register int style;
- int xsz, ysz;
- int redrawn;
-
- if (!w)
- return 0;
-
- wm.xoff = w->BorderLeft;
- wm.yoff = w->BorderTop;
-
- wm.x = w->Width - w->BorderRight - w->BorderLeft;
- wm.width = xsz = wm.x / wm.font.w;
-
- wm.y = w->Height - w->BorderBottom - w->BorderTop;
- wm.height = ysz = wm.y / wm.font.h;
-
- if (np.col80 && xsz > 80)
- xsz = 80;
-
- if (xsz < MINWIDTH || ysz < MINHEIGHT) {
- deinitdrawing();
- showbanner(w->RPort, "Make me BIGGER");
- return 0;
- }
-
- redrawn = initdrawing(w->RPort);
-
- if (!redrawn && xsz == disp.winwidth && ysz == disp.winheight) {
- return redrawn;
- }
-
- BOUNDSCK(xsz, MINWIDTH, disp.maxwidth);
- BOUNDSCK(ysz, MINHEIGHT, disp.maxheight);
-
- if ((disp.scrolltop == 0 && disp.scrollbot == disp.winheight-1) ||
- disp.scrollbot >= ysz)
- disp.scrollbot = ysz-1;
- if (disp.scrolltop >= ysz)
- disp.scrolltop = 0;
- if (disp.cury >= ysz) {
- deinitdrawing();
- dsscroll(0, disp.winheight, disp.cury - ysz + 1);
- initdrawing(w->RPort);
- disp.cury = ysz - 1;
- }
- disp.winwidth = xsz, disp.winheight = ysz;
-
- dssizewindow(xsz, ysz, 0);
-
- DSRESIZE();
-
- niosize(ysz, xsz, wm.x, wm.y);
-
- setnewtitle();
- return 1;
- }
-
- /*
- * Set window size according the given display size
- */
- void dssizewindow(int width, int height, int widthflag)
- {
- if (!w) {
- return;
- } else {
- int ow = w->Width, nw;
- int oh = w->Height, nh;
-
- if (width)
- nw = MIN(width * wm.font.w + w->BorderLeft + w->BorderRight,
- w->WScreen->Width);
- else
- nw = ow;
-
- if (height)
- nh = MIN(height * wm.font.h + w->BorderTop + w->BorderBottom,
- w->WScreen->Height);
- else
- nh = oh;
-
- if ((nw-ow) || (nh-oh)) {
- SizeWindow(w, nw - ow, nh - oh);
- #if 0
- /* wait for resize message */
- WaitPort(w->UserPort);
- #endif
- }
-
- if (np.col80) {
- WindowLimits(w, nw, zoom_size.height, nw, 0);
- } else {
- WindowLimits(w, zoom_size.width, zoom_size.height,
- MAXWIDTH * wm.font.w, MAXHEIGHT * wm.font.h);
- }
- }
- }
-
- /*
- * Handle window and screen titles
- */
- #ifndef MAXHOSTNAMELEN
- #define MAXHOSTNAMELEN 64
- #endif
-
- void setnewtitle(void)
- {
- static char Title[MAXHOSTNAMELEN + 16];
-
- int rows = wm.height, cols = wm.width;
-
- if (np.title)
- strncpy(Title, np.title, sizeof(Title));
- else
- strcpy(Title, ProgName);
- strncat(Title, " (", sizeof(Title));
- strncat(Title, itos(cols), sizeof(Title));
- strncat(Title, " x ", sizeof(Title));
- strncat(Title, itos(rows), sizeof(Title));
- strncat(Title, ")", sizeof(Title));
-
- if (w)
- SetWindowTitles(w, Title, (UBYTE*)ProgName);
- }
-
- #include <errno.h>
-
- /*
- * Print the IO error messages
- */
- void perror(const char *banner)
- {
- const char *error = strerror(errno);
-
- if (started_from_workbench && IntuitionBase != NULL) {
- struct EasyStruct libraryES;
-
- libraryES.es_StructSize = sizeof(libraryES);
- libraryES.es_Flags = 0;
- libraryES.es_Title = ProgName;
- libraryES.es_TextFormat = "%s: %s";
- libraryES.es_GadgetFormat = "Continue";
-
- EasyRequest(w, &libraryES, NULL, banner, error);
- } else {
- Printf("%s: %s\n", banner, error);
- }
- }
-
- void herror(const char *banner, const char *error)
- {
- if (started_from_workbench && IntuitionBase != NULL) {
- struct EasyStruct libraryES;
-
- libraryES.es_StructSize = sizeof(libraryES);
- libraryES.es_Flags = 0;
- libraryES.es_Title = ProgName;
- libraryES.es_TextFormat = "%s: %s";
- libraryES.es_GadgetFormat = "Continue";
-
- EasyRequest(w, &libraryES, NULL, banner, error);
- } else {
- Printf("%s: %s\n", banner, error);
- }
- }
-
- /*
- * Print the error message and die
- */
- void fatalError(const char *s, ...)
- {
- va_list va;
- va_start(va, s);
-
- if (started_from_workbench && IntuitionBase != NULL) {
- struct EasyStruct libraryES;
-
- libraryES.es_StructSize = sizeof(libraryES);
- libraryES.es_Flags = 0;
- libraryES.es_Title = ProgName;
- libraryES.es_TextFormat = s;
- libraryES.es_GadgetFormat = "Quit";
-
- EasyRequestArgs(w, &libraryES, NULL, va);
- } else {
- PutStr(PROGNAME ": ");
- VPrintf(s, (LONG *)va);
- va_end(va);
- PutStr("\n");
- }
-
- dsquit();
- amigaquit();
- exit(130);
- }
-
- /*
- * Menus
- */
- #define MENU_CMD 0
- #define MENU_EDIT 1
- #define MENU_SETUP 2
-
- #if 0
- #define MENU_NATIONAL 3
- static struct Menu nationalmenu = {
- NULL, 120, 0, 55, 10, MENUENABLED, (BYTE *)"National", 0, 0, 0, 0, 0,
- };
- #endif
-
- static struct Menu setupmenu = {
- NULL, 55, 0, 45, 10, MENUENABLED, (BYTE *)"Setup", 0, 0, 0, 0, 0,
- };
-
- static struct Menu editmenu = {
- &setupmenu, 2, 0, 45, 10, MENUENABLED, (BYTE *)"Edit", 0, 0, 0, 0, 0,
- };
-
- static struct Menu cmdmenu = {
- &editmenu, 2, 0, 45, 10, MENUENABLED, (BYTE *)"Command", 0, 0, 0, 0, 0,
- };
-
- /* These macros use some fudge factors to make manus look good */
- /* 9 is space between menus in the menu bar */
- #define MENUWIDTH(menu) (9 + \
- TextLength(&(w->WScreen->RastPort), (menu).MenuName, strlen((menu).MenuName)))
-
- /* 35 is the approximate size of the "A" symbol in the menus */
- #define CMDWIDTH(cmd) (35 + \
- TextLength(&(w->WScreen->RastPort), &(cmd), 1))
-
- #define ITEMWIDTH(str) \
- TextLength(&(w->WScreen->RastPort), (UBYTE*)(str), strlen(str));
-
- /*
- * Menu callback utility functions
- */
- static void menu_state(UBYTE mnum, UBYTE inum, UBYTE subnum, UBYTE enabled)
- {
- struct Menu *menu;
- struct MenuItem *item;
-
- for (menu = &cmdmenu; mnum > 0; mnum--)
- menu = menu->NextMenu;
- for (item = menu->FirstItem; inum > 0; inum--)
- item = item->NextItem;
- /* subnum is ignored for now */
- assert(subnum == NOSUB);
-
- if (enabled)
- item->Flags |= ITEMENABLED;
- else
- item->Flags &= ~ITEMENABLED;
- }
-
-
- /*
- * Menu callback routines
- */
- void menu_move(UBYTE mnum, UBYTE item, UBYTE sub)
- {
- if (isSelection()) {
- char *selstring, *temp;
- if ((temp = selstring = grabSelection())) {
- while (*temp++)
- ;
- nwrite(selstring, temp - selstring - 1);
- FreeVec(selstring);
- }
- }
- }
-
- void menu_execute(UBYTE mnum, UBYTE item, UBYTE sub)
- {
- if (isSelection()) {
- menu_move(mnum, item, sub);
- nwrite("\n", 1);
- }
- }
-
- void menu_copy(UBYTE mnum, UBYTE item, UBYTE sub)
- {
- if (isSelection()) {
- char *selstring = grabSelection();
- ClipCut(selstring);
- FreeVec(selstring);
- }
- }
-
- void menu_paste(UBYTE mnum, UBYTE item, UBYTE sub)
- {
- nwrite(iobuf, ClipPaste(iobuf, sizeof(iobuf)));
- }
-
- void menu_clear(UBYTE mnum, UBYTE item, UBYTE sub)
- {
- dscursoroff();
- if (disp.cury) {
- dsscroll(0, disp.winheight, disp.cury);
- disp.cury = 0;
- }
- dsfunction(ERASETO_EOS);
- dscursoron();
- }
-
- #ifdef TEKTRONICS /*added RKNOP 940328*/
- void menu_totek(UBYTE mnum,UBYTE item,UBYTE sub)
- {
- vt100_tek();
- }
-
- void menu_tovt100(UBYTE mnum,UBYTE item,UBYTE sub)
- {
- tek_vt100();
- }
- #endif
-
- void menu_reset(UBYTE mnum, UBYTE item, UBYTE sub)
- {
- dscursoroff();
- dsfunction(RESET_DISPLAY);
- dscursoron();
- }
-
- void menu_flush(UBYTE mnum, UBYTE item, UBYTE sub)
- {
- nioctl(NIO_FLUSH, 0, 0);
- }
-
- void menu_break(UBYTE mnum, UBYTE item, UBYTE sub)
- {
- nioctl(NIO_BREAK, 0, 0);
- }
-
- #ifdef OWNICONIFY
- void menu_iconify(UBYTE mnum, UBYTE item, UBYTE sub)
- {
- unmapwindow();
- iconify();
- }
- #endif
-
- /*
- * Note: listen must be just before unlisten in its menu!
- */
- void menu_listen(UBYTE mnum, UBYTE item, UBYTE sub)
- {
- menu_state(mnum, item, sub, FALSE);
-
- /* Enable UnListen if nabort() is successful */
- if (!nabort())
- menu_state(mnum, item + 1, sub, TRUE);
- else
- /* otherwise, re-enable us */
- menu_state(mnum, item, sub, TRUE);
-
- ResetMenuStrip(w, &cmdmenu);
- }
-
- void menu_unlisten(UBYTE mnum, UBYTE item, UBYTE sub)
- {
- menu_state(mnum, item, sub, FALSE);
-
- /* Enable Listen if nabort() is successful */
- if (nabort())
- menu_state(mnum, item - 1, sub, TRUE);
- else
- /* otherwise, re-enable us */
- menu_state(mnum, item, sub, TRUE);
-
- ResetMenuStrip(w, &cmdmenu);
- }
-
- void menu_quit(UBYTE mnum, UBYTE item, UBYTE sub)
- {
- dsquit();
- amigaquit();
- exit(0);
- }
-
- /*
- * Callback routines for setup menu -- prototypes on <napsaprefs.h>
- */
- void change_cursor(int mode)
- {
- dscursoroff();
- disp.visual = mode;
- dscursoron();
- }
-
- /* added RKNOP 940328 */
- void change_ansi_LNM(int on)
- { np.ansi_LNM=on;
- }
- /* end added RKNOP 940328 */
-
- void change_invert(int on)
- {
- dsinvert(on ? INVERT_ON : INVERT_OFF);
- }
-
- void change_mode80(int on)
- {
- if (on)
- dssizewindow(80, 0, 1);
- else
- WindowLimits(w, 0, 0, -1, -1);
- #if 0
- redraw_display(1);
- #endif
- }
-
- void change_national(int national)
- {
- (void) redraw_display(0);
- }
-
- void change_nation(int nation)
- {
- setnation(nation);
- if (np.national == NAT_7BIT)
- (void) redraw_display(0);
- }
-
- /*
- * The text of the menu, callback function and the HotKey for it.
- */
- struct menudef {
- char *text;
- void (*call_f)(UBYTE mnum, UBYTE item, UBYTE sub);
- char com;
- unsigned ser : 1; /* active only with serial */
- unsigned off : 1; /* not active by default */
- };
-
- static struct menudef cmd_items[] =
- {
- { "Clear Screen", menu_clear, 'S', },
- #ifdef TEKTRONICS /*added RKNOP 940328*/
- { "To Tek4010", menu_totek, 'G', },
- { "To VT102", menu_tovt100, 'T', },
- #endif
- { "Soft Reset", menu_reset, 'R', },
- { "Flush", menu_flush, 'F', },
- { "Break", menu_break, 'B', 1, },
- { "Listen", menu_listen, 'L', 1, 1, },
- { "Unlisten", menu_unlisten, 'U', 1, },
- { "Quit", menu_quit, 'Q', },
- { NULL, },
- };
-
- static struct menudef edit_items[] =
- {
- { "Copy", menu_copy, 'C', },
- { "Paste", menu_paste, 'V', },
- { "Move", menu_move, 'M', },
- { "Execute", menu_execute, 'E', },
- { NULL, },
- };
-
- /*
- * Initialize a menu item
- */
- static struct MenuItem *inititem(struct MenuItem **first,
- struct MenuItem *last,
- const char *str, char com)
- {
- struct IntuiText *it;
- struct MenuItem *mi;
-
- /*
- * Templates
- */
- static struct MenuItem protoitem = {
- NULL, 0, 0, 0, 0, HIGHCOMP | ITEMTEXT | ITEMENABLED,
- 0, NULL, NULL, 0, NULL, 0
- };
-
- static struct IntuiText prototext = {
- 0, 1, JAM2, 0, 0, NULL, NULL, NULL
- };
-
- mi = (struct MenuItem *)
- AllocVec(sizeof(*mi) + sizeof(*it), MEMF_PUBLIC);
- if (last)
- last->NextItem = mi;
- else
- *first = mi;
-
- if (mi == NULL) {
- fatalError(MEMORY_ERROR_MSG);
- }
-
- it = (struct IntuiText *)(mi + 1);
- *mi = protoitem; *it = prototext;
- mi->TopEdge = last ? last->TopEdge + w->WScreen->RastPort.TxHeight + 1 : 0;
- mi->Height = w->WScreen->RastPort.TxHeight + 1;
- mi->Width = ITEMWIDTH(str);
- mi->ItemFill = (APTR)it;
- if (com) {
- mi->Command = com;
- mi->Flags |= COMMSEQ;
- mi->Width += CMDWIDTH(mi->Command);
- }
- it->TopEdge = 1;
- it->IText = (UBYTE *)str;
- return mi;
- }
-
- static void initmenu(struct Menu *menu, struct menudef newmenu[])
- {
- struct MenuItem *li = NULL;
- long width = 0;
-
- menu->Width = MENUWIDTH(*menu);
-
- for (; newmenu->text; newmenu++) {
- li = inititem(&menu->FirstItem, li, newmenu->text, newmenu->com);
- width = (li->Width > width) ? li->Width : width;
-
- if (iotype != serial && newmenu->ser || newmenu->off) {
- li->Flags &= ~ITEMENABLED;
- }
- }
- for (li = menu->FirstItem; li; li = li->NextItem)
- li->Width = width;
- }
-
- /*
- * Initialize and show menus
- */
- void initmenus(void)
- {
- if (!cmdmenu.FirstItem) {
- long width, me;
- const char *mtxt;
- struct MenuItem *li;
-
- initmenu(&cmdmenu, cmd_items);
- initmenu(&editmenu, edit_items);
- editmenu.LeftEdge = cmdmenu.LeftEdge + cmdmenu.Width;
- setupmenu.Width = MENUWIDTH(setupmenu);
- setupmenu.LeftEdge = editmenu.LeftEdge + editmenu.Width;
-
- for (me = 0, li = NULL, width = 0; mtxt = setup_items[me].title; me++) {
- li = inititem(&setupmenu.FirstItem, li, mtxt, 0);
- if (mtxt = setup_items[me].texts) {
- int subi, val = getsetup(me);
- struct MenuItem *si = NULL;
-
- for (subi = 0; *mtxt; subi++) {
- si = inititem(&li->SubItem, si, mtxt, 0);
- si->MutualExclude = ~(1<<subi);
- si->Flags |= CHECKIT;
- if (subi == val)
- si->Flags |= CHECKED;
- while (*mtxt++)
- ;
- si->Width += CHECKWIDTH;
- ((struct IntuiText *)si->ItemFill)->LeftEdge = CHECKWIDTH;
- }
- } else {
- li->Flags |= CHECKIT | MENUTOGGLE;
- if (getsetup(me))
- li->Flags |= CHECKED;
- li->Width += CHECKWIDTH;
- ((struct IntuiText *)li->ItemFill)->LeftEdge = CHECKWIDTH;
- }
- width = (li->Width > width) ? li->Width : width;
- }
- for (li = setupmenu.FirstItem; li; li = li->NextItem) {
- struct MenuItem *si;
- int subwidth = width / 2;
-
- for (si = li->SubItem; si; si = si->NextItem) {
- si->TopEdge += w->WScreen->RastPort.TxHeight + 2;
- si->LeftEdge = setupmenu.Width;
- subwidth = (si->Width > subwidth) ? si->Width : subwidth;
- }
- for (si = li->SubItem; si; si = si->NextItem) {
- si->Width = subwidth;
- }
- li->Width = width;
- }
-
- #if 0
- nationalmenu.Width = MENUWIDTH(nationalmenu);
-
- for (me = 0, li = NULL, width = 0; mtxt = getnationname(me); me++) {
- li = inititem(&nationalmenu.FirstItem, li, mtxt, 0);
- li->MutualExclude = ~(1<<me);
- li->Flags |= CHECKIT;
- if (me == getnationnumber())
- li->Flags |= CHECKED;
- width = (li->Width > width) ? li->Width : width;
- }
- width += CHECKWIDTH;
- for (li = nationalmenu.FirstItem; li; li=li->NextItem) {
- li->Width = width;
- ((struct IntuiText *)li->ItemFill)->LeftEdge = CHECKWIDTH;
- }
- #endif
- }
-
- SetMenuStrip(w, &cmdmenu);
- }
-
- void deinitmenus(void)
- {
- struct Menu *menu;
- struct MenuItem *mi, *ni, *si, *sni;
-
- for (menu = &cmdmenu; menu; menu = menu->NextMenu) {
- for (mi = menu->FirstItem; mi; mi = ni) {
- ni = mi->NextItem;
- for (si = mi->SubItem; si; si = sni) {
- sni = si->NextItem;
- FreeVec(si), si = NULL;
- }
- FreeVec(mi), mi = NULL;
- }
- menu->FirstItem = NULL;
- }
- }
-
- /*
- * Setup menu dispatcher
- */
- static void domenu_setup(register UBYTE which, register BYTE sub)
- {
- register BYTE new, cleared = 0;
- struct MenuItem *mi, *si;
-
- /* We will get no extra events for extended selection */
- for (which = 0, mi = setupmenu.FirstItem; mi; mi = mi->NextItem, which++) {
- if (si = mi->SubItem) {
- for (sub = 0; si; sub++, si = si->NextItem) {
- if ((si->Flags & CHECKED) == CHECKED)
- break;
- }
- /* None was checked.. */
- if (!si)
- sub = -1;
- } else {
- sub = (mi->Flags & CHECKED) == CHECKED;
- }
- new = changesetup(which, sub);
- if (sub != new) {
- if (!cleared)
- ClearMenuStrip(w);
- cleared = 1;
- if (si = mi->SubItem) {
- /* Check an item in submenu */
- for (sub = 0; si; sub++, si = si->NextItem) {
- if (sub == new)
- si->Flags |= CHECKED;
- else
- si->Flags &= ~CHECKED;
- }
- } else {
- if (new)
- mi->Flags |= CHECKED;
- else
- mi->Flags &= ~CHECKED;
- }
- }
- }
-
- /*
- * Redraw menu
- */
- if (cleared)
- ResetMenuStrip(w, &cmdmenu);
- }
-
- /*
- * National menu dispatcher
- */
- static void domenu_nation(register UBYTE nation, register UBYTE sub)
- {
- setnation(nation);
- (void) redraw_display(0);
- }
-
- /*
- * Menu dispatcher
- */
- void domenu(register struct IntuiMessage *msg)
- {
- register ULONG code = msg->Code;
- register UBYTE mnum = MENUNUM(code);
- register UBYTE item = ITEMNUM(code);
- register UBYTE sub = SUBNUM(code);
-
- ReplyMsg(msg), msg = NULL;
-
- /* so we know that item is always valid */
- if (code == MENUNULL || mnum == NOMENU || item == NOITEM)
- return;
-
- switch (mnum) {
- case MENU_CMD:
- if (cmd_items[item].call_f)
- cmd_items[item].call_f(mnum, item, sub);
- break;
- case MENU_EDIT:
- if (edit_items[item].call_f)
- edit_items[item].call_f(mnum, item, sub);
- break;
- case MENU_SETUP:
- domenu_setup(item, sub);
- break;
- #if 0
- case MENU_NATIONAL:
- domenu_nation(item, sub);
- break;
- #endif
- }
- }
-